package com.hzit.manager.service.impl;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphO;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.hzit.manager.handler.MyFallbackHandler;
import com.hzit.manager.handler.MyBlockHandler;
import com.hzit.manager.service.SentineService;
import org.springframework.stereotype.Service;

/**
 * 类名：
 * 作者：WF
 * 功能：
 */
@Service
public class SentineServiceImpl implements SentineService {
	@Override
	public String myRes1() {
		try (Entry entry = SphU.entry("res1")) {
			// 被保护的业务逻辑
			System.out.println("1.抛出异常的方式定义资源！");
		} catch (BlockException ex) {
			// 资源访问阻止，被限流或被降级
		    return "资源1被限流了！";
		}
		return "hello,res1";
	}

	@Override
	public String myRes2() {
		// 资源名可使用任意有业务语义的字符串
		if (SphO.entry("res2")) {
			// 务必保证finally会被执行
			try {
				System.out.println("2.返回布尔值方式定义资源！");
			} finally {
				SphO.exit();
			}
		} else {
			// 资源访问阻止，被限流或被降级
			// 进行相应的处理操作
			return "资源2被限流了！";
		}
		return "hello,res2";
	}

	//3. 使用@SentinelResource注解定义资源并处理异常
	@SentinelResource(value="res3",blockHandler="myBlock1")
	@Override
	public String myRes3() {
		return "3.使用@SentinelResource注解定义与处理资源-blockHandler处理资源！";
	}

	// 资源处理函数要求：
	//1. 必须与定义的资源在同一个类中，并且必须是public
	//2. 与原函数有相同的返回值类型
	//3. 方法的参数与原函数一致，在参数的最后添加一个BlockException对象
	public  String myBlock1(BlockException be){
		return "资源3出现异常（使用BlockHandler处理异常）,原因是：" + be;
	}

	//3. 使用@SentinelResource注解定义资源并处理异常,使用blockHandlerClass属性处理
	@Override
	@SentinelResource(value = "res4",blockHandlerClass = MyBlockHandler.class,blockHandler = "myBlock2")
	public String myRes4() {
		return "4.使用@SentinelResource注解定义与处理资源-blockHandlerClass处理资源！";
	}

	//4. 使用@SentinelResource注解定义资源并处理异常
	// 使用fallback处理Throwable类型的异常，要注意方法定义：
	// ① 方法必须是public static的
	// ② 方法的返回值类型，参数必须与原函数一致。
	// ③ 方法的参数的最后可以添加一个Throwable类型的对象。
	@Override
	@SentinelResource(value = "res5",fallback = "myBlock2")
	public String myRes5() {
		int i = 10 / 0;
		return "3.使用@SentinelResource注解定义与处理资源-fallback处理资源！";
	}

	@Override
	@SentinelResource(value = "res5",fallback = "myBlock2",fallbackClass = MyFallbackHandler.class)
	public String myRes6() {
		String str = null;
		str.length();
		return "3.使用@SentinelResource注解定义与处理资源-fallbackclass处理资源！";
	}

	public String myBlock2(Throwable t){
		return "资源5出现异常（使用fallback处理异常）,原因是：" + t;
	}

}
